package scatter.common.rest.service;

import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.util.Assert;
import scatter.common.pojo.po.BasePo;
import scatter.common.pojo.po.BaseTreePo;
import scatter.common.rest.dataconstraint.DataConstraintService;
import scatter.common.rest.mapstruct.IBaseUpdateFormMapStruct;

import java.util.List;

/**
 * 修改基础父接口
 * Created by yangwei
 * Created at 2021/1/5 9:47
 */
public interface IBaseUpdateFormService<Po extends BasePo,UpdateForm> extends IBaseService<Po> {

    IBaseUpdateFormMapStruct<Po,UpdateForm> getUpdateFormMapStruct();

    List<IUpdateServiceListener<Po,UpdateForm>> getUpdateServiceListeners();

    /**
     * 数据范围约束服务
     * @return
     */
    DataConstraintService getUpdateDataConstraintService();
    /**
     * 查询前构造查询条件
     * @param queryWrapper
     * @return
     */
    default Wrapper<Po> prepareUpdateFormQueryWrapper(Wrapper<Po> queryWrapper){

        return queryWrapper;
    }
    /**
     * 更新前
     * @param updateForm
     */
    default void preUpdate(UpdateForm updateForm,Po po){}
    /**
     * 更新前
     * @param updateForm
     * @param options
     */
    default void preUpdate(UpdateForm updateForm,Po po,Object options){
        // 树相关
        if (po instanceof BaseTreePo) {
            // 判断父级是否修改
            Po poDb = getById(po.getId());
            //父级不相等，则有修改父级
            if(!isEqual(((BaseTreePo) poDb).getParentId(), ((BaseTreePo) po).getParentId())){
                // 判断该节点下是否有子节点，如果有，不允许修改
                int childrenCount = getChildrenCount(((BaseTreePo) po).getId());

                Assert.isTrue(childrenCount == 0,"当前节点下还有子节点，不允许修改父节点");
            }
            if (!isStrEmpty(((BaseTreePo) po).getParentId())) {
                Assert.isTrue(!isEqual(((BaseTreePo) po).getId(),((BaseTreePo) po).getParentId()),"不能将父级设置为自己");
                initParentIdXByParent(po, ((BaseTreePo) po).getParentId());
            }
        }
        preUpdate(updateForm,po);
        if (!isEmpty(getUpdateServiceListeners())) {
            getUpdateServiceListeners().parallelStream().forEach(listener->listener.preUpdate(updateForm,po));
        }
    }
    /**
     * 修改 使用该方法可以将字段修改为null
     * @param updateForm
     * @return
     */
    default boolean update(UpdateForm updateForm) {
        Assert.isTrue(ReflectUtil.hasField(updateForm.getClass(), BasePo.PROPERTY_ID),"updateForm必须包含主键" + BasePo.PROPERTY_ID);
        Po po = getUpdateFormMapStruct().updateFormToPo(updateForm);
        preUpdate(updateForm,po,null);
        UpdateWrapper<Po> updateWrapper = Wrappers.update();
        annotationSupportUpdateWrapper(updateWrapper,updateForm);
        updateWrapper.eq(BasePo.COLUMN_ID, ReflectUtil.getFieldValue(updateForm, BasePo.PROPERTY_ID));
        // 数据范围约束
        getUpdateDataConstraintService().dataConstraint(updateWrapper);
        prepareUpdateFormQueryWrapper(updateWrapper);
        boolean r = update(po,updateWrapper);
        if (r) {
            postUpdate(updateForm,po,null);
        }
        return r;
    }

    /**
     * 更新后
     * @param updateForm
     * @param po
     */
    default void postUpdate(UpdateForm updateForm,Po po){}

    /**
     * 更新后
     * @param updateForm
     * @param po
     * @param options
     */
    default void postUpdate(UpdateForm updateForm,Po po,Object options){
        postUpdate(updateForm,po);
        if (!isEmpty(getUpdateServiceListeners())) {
            getUpdateServiceListeners().parallelStream().forEach(listener->listener.postUpdate(updateForm,po));
        }
    }
}
